package com.chris.libs.base.x.mvpp.recycler;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 分组列表的分割线
 *
 * @param <G>   Group数据类型
 * @param <GVH> ViewHolder of the group
 * @param <CVH> ViewHolder of the child
 *              Created by Chris Chen on 2020/7/17 02:30.
 *              Explain:
 */
public abstract class BaseGroupRecyclerAdapter<G, GVH extends BaseRecyclerHolder<G>, C, CVH extends BaseRecyclerHolder<C>>
        extends RecyclerView.Adapter {
    protected Context context;

    public static final int INVALID_POSITION = -1;

    private static final int TYPE_GROUP = 1;
    private static final int TYPE_CHILD = 2;

    protected List<G> groupDataList;
    protected View groupItemView, childItemView;
    protected int itemCount;

    private OnItemClickListener<G, C> onItemClickListener;

    public BaseGroupRecyclerAdapter(Context context) {
        this(context, new ArrayList<>(16));
    }

    public BaseGroupRecyclerAdapter(Context context, List<G> groups) {
        this.context = context;
        groupDataList = (groups == null ? new ArrayList<>(16) : groups);
        updateItemCount();
    }

    public BaseGroupRecyclerAdapter(Context context, G... groups) {
        this(context, Arrays.asList(groups));
    }

    public void setOnItemClickListener(OnItemClickListener<G, C> onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    @Override
    public BaseRecyclerHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == TYPE_GROUP) {
            groupItemView = LayoutInflater.from(context).inflate(groupLayoutId(), parent, false);
            return onCreateGroupViewHolder(groupItemView);
        } else {
            childItemView = LayoutInflater.from(context).inflate(childLayoutId(), parent, false);
            return onCreateChildViewHolder(childItemView);
        }
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int itemPosition) {
        Position position = getGroupChildPosition(itemPosition);
        if (position.child == INVALID_POSITION) {
            onBindGroupViewHolder((GVH) holder, position.group);
        } else {
            onBindChildViewHolder((CVH) holder, position.group, position.child);
        }
    }

    public Position getGroupChildPosition(int itemPosition) {
        int itemCount = 0;
        int childCount;
        final Position position = new Position();
        for (G g : groupDataList) {
            if (itemPosition == itemCount) {
                position.child = INVALID_POSITION;
                return position;
            }
            itemCount++;
            childCount = getChildCount(g);
            if (childCount > 0) {
                position.child = itemPosition - itemCount;
                if (position.child < childCount) {
                    return position;
                }
                itemCount += childCount;
            }
            position.group++;
        }
        return position;
    }

    protected void onBindGroupViewHolder(GVH holder, int groupPosition) {
        groupItemView.setOnClickListener(view -> {
            if (onItemClickListener != null) {
                onItemClickListener.onGroupItemClick(groupItemView, groupPosition, getGroupData(groupPosition));
            }
        });

        refreshGroupView(holder, groupPosition);
    }

    protected void onBindChildViewHolder(CVH holder, int groupPosition, int childPosition) {
        childItemView.setOnClickListener(view -> {
            if (onItemClickListener != null) {
                onItemClickListener.onChildItemClick(childItemView, groupPosition, childPosition, getChildData(groupPosition, childPosition));
            }
        });

        refreshChildView(holder, groupPosition, childPosition);
    }

    protected void refreshGroupView(GVH holder, int groupPosition) {
        refreshGroupItemView(holder, getGroupData(groupPosition));
    }

    protected void refreshChildView(CVH holder, int groupPosition, int childPosition) {
        refreshChildItemView(holder, getChildData(groupPosition, childPosition));
    }

    @Override
    public int getItemCount() {
        return itemCount;
    }

    @Override
    public int getItemViewType(int position) {
        return getItemType(position) == ItemType.GROUP_TITLE ? TYPE_GROUP : TYPE_CHILD;
    }

    private void updateItemCount() {
        int count = 0;
        for (G group : groupDataList) {
            count += getChildCount(group) + 1;
        }
        itemCount = count;
    }

    public int getGroupCount() {
        return groupDataList.size();
    }

    protected abstract int groupLayoutId();

    protected abstract int childLayoutId();

    protected abstract C getChildData(int groupPosition, int childPosition);

    protected abstract int getChildCount(G group);

    protected abstract GVH onCreateGroupViewHolder(View groupItemView);

    protected abstract CVH onCreateChildViewHolder(View childItemView);

    protected abstract void refreshGroupItemView(GVH holder, G groupItem);

    protected abstract void refreshChildItemView(CVH holder, C childItem);

    /**
     * 更新
     *
     * @param groupDataList
     */
    public void updateData(List<G> groupDataList) {
        this.groupDataList = groupDataList;
        updateItemCount();
        notifyDataSetChanged();
    }

    /**
     * 更新
     *
     * @param groupDatas
     */
    public void updateData(G... groupDatas) {
        if (null == groupDatas || groupDatas.length == 0) {
            return;
        }
        updateData(Arrays.asList(groupDatas));
    }

    /**
     * 加载更多
     *
     * @param groupDataList
     */
    public void loadMore(List<G> groupDataList) {
        if (null == this.groupDataList) {
            this.groupDataList = new ArrayList<>(16);
        }
        if (null == groupDataList || groupDataList.size() == 0) {
            return;
        }
        int lastCount = getItemCount();
        addGroups(groupDataList);
        updateItemCount();
        notifyItemRangeInserted(lastCount, itemCount - lastCount);
    }

    /**
     * 加载更多
     *
     * @param groupDatas
     */
    public void loadMore(G... groupDatas) {
        if (null == this.groupDataList) {
            this.groupDataList = new ArrayList<>(16);
        }
        if (null == groupDatas || groupDatas.length == 0) {
            return;
        }
        loadMore(Arrays.asList(groupDatas));
    }

    private void addGroups(List<G> groups) {
        if (groups != null && groups.size() > 0) {
            groupDataList.addAll(groups);
        }
    }

    public G getGroupData(int groupPosition) {
        return groupDataList.get(groupPosition);
    }

    public ItemType getItemType(final int itemPosition) {
        int count = 0;
        int childCount;
        for (G g : groupDataList) {
            if (itemPosition == count) {
                return ItemType.GROUP_TITLE;
            }
            childCount = getChildCount(g);
            count += 1;
            if (itemPosition == count && childCount != 0) {
                return ItemType.FIRST_CHILD;
            }
            count += childCount;
            if (itemPosition < count) {
                return ItemType.NOT_FIRST_CHILD;
            }
        }
        throw new IllegalStateException("Could not find item type for item position " + itemPosition);
    }

    public enum ItemType {
        GROUP_TITLE,
        FIRST_CHILD,
        NOT_FIRST_CHILD
    }

    public static class Position {
        public int group;
        public int child = INVALID_POSITION;
    }

    /**
     * 列表项点击监听
     *
     * @param <G>
     * @param <C>
     */
    public interface OnItemClickListener<G, C> {
        default void onGroupItemClick(View groupItemView, int groupPosition, G groupData) {
        }

        default void onChildItemClick(View childItemView, int groupPosition, int childPosition, C childData) {
        }
    }
}
